use crate::core::message::{AppEvent, EventSender, GitResult};
use anyhow::Result;
use tokio::{sync::oneshot, task};

/// Git 操作管理器，负责创建和管理异步 Git 操作
#[derive(Clone)]
pub struct GitManager {
    event_sender: EventSender,
}

impl GitManager {
    pub fn new(event_sender: EventSender) -> Self {
        Self { event_sender }
    }

    /// 检查仓库状态并加载初始数据
    pub async fn check_repository(&self) -> Result<()> {
        let tx = self.event_sender.clone();

        tokio::spawn(async move {
            match crate::git::commands::is_git_repository().await {
                true => {
                    // 获取当前分支
                    if let Ok(branch) = crate::git::commands::get_current_branch().await {
                        let _ = tx
                            .send(AppEvent::GitOperationComplete {
                                operation: "check_repository".to_string(),
                                result: GitResult::CurrentBranch(branch.clone()),
                            })
                            .await;
                    }

                    // 获取所有分支
                    match crate::git::commands::get_branches().await {
                        Ok(branches) => {
                            let _ = tx
                                .send(AppEvent::GitOperationComplete {
                                    operation: "check_repository".to_string(),
                                    result: GitResult::Branches(branches.clone()),
                                })
                                .await;

                            if !branches.is_empty() {
                                let _ =
                                    tx.send(AppEvent::BranchSelected(branches[0].clone())).await;
                            } else {
                                // 添加空分支列表处理
                                let _ = tx
                                    .send(AppEvent::GitOperationComplete {
                                        operation: "check_repository".to_string(),
                                        result: GitResult::Branches(Vec::new()),
                                    })
                                    .await;
                            }
                        }
                        Err(e) => {
                            let _ = tx
                                .send(AppEvent::GitOperationError {
                                    operation: "check_repository".to_string(),
                                    error: e.to_string(),
                                })
                                .await;
                        }
                    }
                }
                false => {
                    let _ = tx
                        .send(AppEvent::GitOperationError {
                            operation: "check_repository".to_string(),
                            error: "Not in a git repository".to_string(),
                        })
                        .await;
                }
            }
        });

        Ok(())
    }

    /// 检查分支状态
    pub async fn check_branch_status(&self, branch_name: &str) -> Result<()> {
        let tx = self.event_sender.clone();
        let branch_name = branch_name.to_string();

        tokio::spawn(async move {
            // 这里可以添加分支状态检查逻辑
            // 获取分支提交历史
            match crate::git::commands::get_branch_commits(&branch_name).await {
                Ok(commits) => {
                    let _ = tx
                        .send(AppEvent::GitOperationComplete {
                            operation: format!("branch_status:{}", branch_name),
                            result: GitResult::Commits(commits),
                        })
                        .await;
                }
                Err(e) => {
                    let _ = tx
                        .send(AppEvent::GitOperationError {
                            operation: format!("branch_status:{}", branch_name),
                            error: e.to_string(),
                        })
                        .await;
                }
            }
        });

        Ok(())
    }

    /// 切换分支
    pub fn checkout_branch(&self, branch_name: &str, force: bool) -> CancellableGitOperation<()> {
        let tx = self.event_sender.clone();
        let branch_name = branch_name.to_string();

        // 发送操作开始事件
        let _ = tx.send(AppEvent::GitOperationStart {
            operation: format!("checkout_branch:{}", branch_name),
        });

        let (cancel_tx, cancel_rx) = oneshot::channel();

        let task = tokio::spawn(async move {
            let result =
                crate::git::commands::checkout_branch(&branch_name, force, Some(cancel_rx)).await;

            match result {
                Ok(_) => {
                    let _ = tx
                        .send(AppEvent::GitOperationComplete {
                            operation: format!("checkout_branch:{}", branch_name),
                            result: GitResult::Success,
                        })
                        .await;
                    Ok(())
                }
                Err(e) => {
                    let _ = tx
                        .send(AppEvent::GitOperationError {
                            operation: format!("checkout_branch:{}", branch_name),
                            error: e.to_string(),
                        })
                        .await;
                    Err(e)
                }
            }
        });

        CancellableGitOperation::new(task, cancel_tx)
    }

    /// 获取仓库状态
    pub async fn get_repo_status(&self) -> Result<()> {
        let tx = self.event_sender.clone();

        let _ = tx
            .send(AppEvent::GitOperationStart {
                operation: "repo_status".to_string(),
            })
            .await;

        tokio::spawn(async move {
            match crate::git::commands::get_repository_status().await {
                Ok(status) => {
                    let _ = tx
                        .send(AppEvent::GitOperationComplete {
                            operation: "repo_status".to_string(),
                            result: GitResult::RepoStatus(status), // 修改为包含 has_changes
                        })
                        .await;
                }
                Err(e) => {
                    let _ = tx
                        .send(AppEvent::GitOperationError {
                            operation: "repo_status".to_string(),
                            error: e.to_string(),
                        })
                        .await;
                }
            }
        });

        Ok(())
    }

    /// 获取分支差异提交（源分支有但目标分支没有的提交）
    pub async fn get_branch_diff_commits(
        &self,
        source_branch: &str,
        target_branch: &str,
    ) -> Result<()> {
        let tx = self.event_sender.clone();
        let source_branch = source_branch.to_string();
        let target_branch = target_branch.to_string();

        let _ = tx
            .send(AppEvent::GitOperationStart {
                operation: format!("branch_diff:{}", source_branch),
            })
            .await;

        tokio::spawn(async move {
            match crate::git::commands::get_branch_diff_commits(&source_branch, &target_branch)
                .await
            {
                Ok(commits) => {
                    let _ = tx
                        .send(AppEvent::GitOperationComplete {
                            operation: format!("branch_diff:{}", source_branch),
                            result: GitResult::Commits(commits),
                        })
                        .await;
                }
                Err(e) => {
                    let _ = tx
                        .send(AppEvent::GitOperationError {
                            operation: format!("branch_diff:{}", source_branch),
                            error: e.to_string(),
                        })
                        .await;
                }
            }
        });

        Ok(())
    }
    /// 合并指定的提交到当前分支
    pub fn merge_commits(
        &self,
        source_branch: &str,
        commit_ids: Vec<String>,
    ) -> CancellableGitOperation<()> {
        let tx = self.event_sender.clone();
        let source_branch = source_branch.to_string();
        let commit_ids_clone = commit_ids.clone();

        // 发送操作开始事件
        let _ = tx.send(AppEvent::GitOperationStart {
            operation: format!("merge_commits:{}", source_branch),
        });

        let (cancel_tx, cancel_rx) = oneshot::channel();

        let task = tokio::spawn(async move {
            let result = crate::git::commands::merge_commits(
                &source_branch,
                &commit_ids_clone,
                Some(cancel_rx),
            )
            .await;

            match result {
                Ok(_) => {
                    // 发送合并成功事件
                    let _ = tx
                        .send(AppEvent::GitOperationComplete {
                            operation: format!("merge_commits:{}", source_branch),
                            result: GitResult::MergeSuccess,
                        })
                        .await;
                    Ok(())
                }
                Err(e) if e.to_string().contains("conflict") => {
                    // 如果错误信息包含冲突，则发送合并冲突事件
                    let conflicts = Vec::new(); // 这里应该从错误中提取冲突文件列表
                    let _ = tx
                        .send(AppEvent::GitOperationComplete {
                            operation: format!("merge_commits:{}", source_branch),
                            result: GitResult::MergeConflict { conflicts },
                        })
                        .await;
                    Err(e)
                }
                Err(e) => {
                    let _ = tx
                        .send(AppEvent::GitOperationError {
                            operation: format!("merge_commits:{}", source_branch),
                            error: e.to_string(),
                        })
                        .await;
                    Err(e)
                }
            }
        });

        CancellableGitOperation::new(task, cancel_tx)
    }
}

/// 可取消的 Git 操作
pub struct CancellableGitOperation<T> {
    task: task::JoinHandle<Result<T>>,
    cancel: oneshot::Sender<()>,
}

impl<T> CancellableGitOperation<T> {
    pub fn new(task: task::JoinHandle<Result<T>>, cancel: oneshot::Sender<()>) -> Self {
        Self { task, cancel }
    }

    pub fn cancel(self) {
        let _ = self.cancel.send(());
    }

    pub async fn wait(self) -> Result<T> {
        self.task.await?
    }
}
